/* gvSIG. Geographic Information System of the Valencian Government
 *
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
 * of the Valencian Government (CIT)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 *
 */
package org.gvsig.raster.osm.app.osmclient;

import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyVetoException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

import org.cresques.cts.IProjection;
import org.gvsig.andami.Launcher;
import org.gvsig.andami.PluginServices;
import org.gvsig.andami.PluginsLocator;
import org.gvsig.andami.ui.mdiManager.IWindow;
import org.gvsig.app.ApplicationLocator;
import org.gvsig.app.ApplicationManager;
import org.gvsig.app.gui.WizardPanel;
import org.gvsig.app.gui.wizards.WizardListener;
import org.gvsig.app.gui.wizards.WizardListenerSupport;
import org.gvsig.app.project.ProjectManager;
import org.gvsig.app.project.documents.view.ViewDocument;
import org.gvsig.app.project.documents.view.ViewManager;
import org.gvsig.app.project.documents.view.gui.AbstractViewPanel;
import org.gvsig.app.project.documents.view.gui.IView;
import org.gvsig.fmap.crs.CRSFactory;
import org.gvsig.fmap.dal.DALLocator;
import org.gvsig.fmap.dal.DataParameters;
import org.gvsig.fmap.dal.DataStoreParameters;
import org.gvsig.fmap.dal.coverage.RasterLocator;
import org.gvsig.fmap.dal.coverage.store.parameter.TileDataParameters;
import org.gvsig.fmap.dal.coverage.util.FileUtils;
import org.gvsig.fmap.dal.exception.InitializeException;
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
import org.gvsig.fmap.mapcontext.MapContext;
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
import org.gvsig.fmap.mapcontrol.MapControl;
import org.gvsig.raster.osm.app.osmclient.layer.FLyrOSM;
import org.gvsig.raster.osm.io.OSMDataParameters;
import org.gvsig.raster.osm.io.OSMProvider;
import org.gvsig.raster.osm.swing.AddOSMLayerPanel;
import org.gvsig.raster.osm.swing.OSMSwingLocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Wizard panel to add a new OSM raster layer
 * @author Nacho Brodin (nachobrodin@gmail.com)
 */
public class AddOSMLayerWizard extends WizardPanel implements MouseListener {
	private static final long           serialVersionUID      = 1L;
	private static final String         TAB_NAME              = "OSM";
	private static Logger               logger                = LoggerFactory.getLogger(AddOSMLayerWizard.class.getName());
	private AbstractViewPanel           view                  = null;
	private AddOSMLayerPanel            apiUI                 = null;
	private WizardListenerSupport       listenerSupport       = null;
	
	
	public AddOSMLayerWizard() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 *
	 * @return void
	 */
	private void initialize() {
		setTabName(PluginServices.getText(this, TAB_NAME));
		setLayout(new GridBagLayout());
		GridBagConstraints gridBagConstraints = new GridBagConstraints();
		gridBagConstraints.fill = GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		gridBagConstraints.insets = new Insets(6, 6, 6, 6);

		IWindow iw = PluginServices.getMDIManager().getActiveWindow();

		if (iw == null) {
			return;
		}

		if (!(iw instanceof AbstractViewPanel)) {
			return;
		}
		
		apiUI = OSMSwingLocator.getSwingManager().createAddOSMLayerPanel(new File(Launcher.getAppHomeDir()));
		
		//Copying osmservers.properties
		if(!new File(apiUI.getPropertiesFilePath()).exists()) {
			File pluginFolder = PluginsLocator.getManager().getPluginsFolder();
			File f = new File(pluginFolder.getAbsolutePath() + 
							File.separator + 
							"org.gvsig.raster.osm.app.osmclient" + 
							File.separator + 
							apiUI.getPropertiesFileName());
			FileUtils utils = RasterLocator.getManager().getFileUtils();
			try {
				utils.copyFile(f.getAbsolutePath(), Launcher.getAppHomeDir() + File.separator);
				apiUI = OSMSwingLocator.getSwingManager().createAddOSMLayerPanel(new File(Launcher.getAppHomeDir()));
			} catch (FileNotFoundException e) {
				logger.info("File not found copying osmservers.properties", e);
			} catch (IOException e) {
				logger.info("Error copying osmservers.properties", e);
			}
		}
		
		apiUI.addMouseListener(this);
		
		view = (AbstractViewPanel) iw;
		setMapCtrl(view.getMapControl());
		
		JPanel mainPanel = (JPanel)apiUI.getComponent();
		add(mainPanel, gridBagConstraints);
	}
	
	private WizardListenerSupport getWizardListenerSupport() {
		if(listenerSupport == null)
			listenerSupport = new WizardListenerSupport();
		return listenerSupport;
	}
	
	/**
	 * This method checks for the options selected within the configuration
	 * dialog are correct.
	 *
	 * @return true if you're done, false if not.
	 */
	public boolean areSettingsValid() {
		return apiUI.areSettingsValid(); 
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.app.gui.WizardPanel#addWizardListener(org.gvsig.app.gui.wizards.WizardListener)
	 */
	public void addWizardListener(WizardListener listener) {
		getWizardListenerSupport().addWizardListener(listener);
		getWizardListenerSupport().callStateChanged(false);
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.app.gui.WizardPanel#removeWizardListener(org.gvsig.app.gui.wizards.WizardListener)
	 */
	public void removeWizardListener(WizardListener listener) {
		getWizardListenerSupport().removeWizardListener(listener);
	}
	
	@Override
	public void close() {
		
	}

	@Override
	public void execute() {
		DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
		try {
			OSMDataParameters parameters = (OSMDataParameters)dataman.createStoreParameters(OSMProvider.NAME);
			parameters.setURI(apiUI.getSelectedURL());
			parameters.setTileSuffix(apiUI.getSelectedFormat());
			parameters.setOSMLayerName(apiUI.getSelectedName());
			try {
				parameters.setNumberOfLevels(new Integer(apiUI.getSelectedLevel()));
			} catch (NumberFormatException e) {
				
			}
			
			TileDataParameters tileParams = (TileDataParameters) dataman.createStoreParameters("Tile Store");
			tileParams.setDataParameters((DataParameters)parameters);
			
			//Creating a OSM layer
			FLyrOSM layer = new FLyrOSM();
			layer.deleteCache(false);  //Esto es parametrizable
			try {
				layer.setParameters(tileParams);
				layer.setName(apiUI.getSelectedName());
			} catch (InitializeException e) {
				messageBoxInfo("error_initializing_layer", PluginServices.getMDIManager().getActiveWindow(), e);
			}
			
			//Getting the MapContext
			MapControl mapCtrl = null;
			MapContext mapContext = null;
			IWindow[] w = PluginServices.getMDIManager().getAllWindows();
			for (int i = 0; i < w.length; i++) {
				if (w[i] instanceof org.gvsig.app.project.documents.view.gui.AbstractViewPanel) {
					mapCtrl = ((org.gvsig.app.project.documents.view.gui.AbstractViewPanel)w[i]).getMapControl();
					mapContext = mapCtrl.getMapContext();
				}
			}
			
			if(mapContext == null) {
				mapContext = createViewWindow();
			}
			
			//Adding the layer
			mapContext.beginAtomicEvent();
			layer.setVisible(true);
			mapContext.getLayers().addLayer(layer);
			mapContext.callLegendChanged();
			mapContext.endAtomicEvent();
			
		} catch (InitializeException e) {
			messageBoxInfo("error_creating_parameters", PluginServices.getMDIManager().getActiveWindow(), e);
		} catch (ProviderNotRegisteredException e) {
			messageBoxInfo("error_creating_parameters", PluginServices.getMDIManager().getActiveWindow(), e);
		} catch (LoadLayerException e) {
			messageBoxInfo("error_creating_the_view", PluginServices.getMDIManager().getActiveWindow(), e);
		}
	}
	
	private void messageBoxInfo(String msg, Object parentWindow, Exception exception) {
		LoggerFactory.getLogger(getClass()).debug(msg, exception);
		String string = PluginServices.getText(parentWindow, "accept");
		Object[] options = {string};
		JOptionPane.showOptionDialog((Component)/*PluginServices.getMainFrame()*/parentWindow,
					"<html>" + PluginServices.getText(parentWindow, msg).replaceAll("\n", "<br>") + "</html>",
					PluginServices.getText(parentWindow, "confirmacion"),
					JOptionPane.OK_OPTION,
					JOptionPane.INFORMATION_MESSAGE,
					null,
					options,
					string);
	}
	
	/**
     * Create the view in the project. Add the blocks layer
     * to the view, and register the tool for get info of the
     * blocks.
     */
    @SuppressWarnings("deprecation")
	private MapContext createViewWindow() throws LoadLayerException {
    	ApplicationManager application = ApplicationLocator.getManager();

    	ProjectManager projectManager = application.getProjectManager();

    	// 1. Create a new view and set the name.
    	ViewManager viewManager = (ViewManager) projectManager.getDocumentManagers(ViewManager.TYPENAME);
    	ViewDocument view = (ViewDocument) viewManager.createDocument();
    	view.setName("OpenStreetMap View");

    	// 4. Add the view to the current project.
    	projectManager.getCurrentProject().add(view);

    	// 5. Force to show the view's window.
    	IView viewWindow = (IView) viewManager.getMainWindow(view);

    	application.getUIManager().addWindow(viewWindow, GridBagConstraints.CENTER);
    	try {
			application.getUIManager().setMaximum((IWindow) viewWindow, true);
		} catch (PropertyVetoException e) {
		}
    	
		if(viewWindow != null) {
			IProjection proj = CRSFactory.getCRS("3785");
			if(proj != null)
				viewWindow.getMapControl().setProjection(proj);
			return viewWindow.getMapControl().getMapContext();
		}
		return null;
    }

	@Override
	public DataStoreParameters[] getParameters() {
		return null;
	}

	@Override
	public void initWizard() {
		
	}

	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void mousePressed(MouseEvent e) {
		getWizardListenerSupport().callStateChanged(true);
	}

	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	
}
